home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / !runtime / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  5.9 KB  |  250 lines  |  [TEXT/R*ch]

  1. /* Start-up code */
  2.  
  3. #include <stdio.h>
  4. #include <fcntl.h>
  5. #include <sys/types.h>
  6. #include "version.h"
  7. #include "alloc.h"
  8. #include "exec.h"
  9. #include "fail.h"
  10. #include "gc.h"
  11. #include "globals.h"
  12. #include "intext.h"
  13. #include "io.h"
  14. #include "misc.h"
  15. #include "mlvalues.h"
  16. #include "stacks.h"
  17. #include "sys.h"
  18.  
  19. #ifndef macintosh
  20. #ifdef __STDC__
  21. #include <stdlib.h>
  22. #else
  23. extern char *getenv ();
  24. #endif /* __STDC__ */
  25. #endif /* not macintosh */
  26.  
  27. extern value interprete();
  28.  
  29. #ifndef O_BINARY
  30. #define O_BINARY 0
  31. #endif
  32.  
  33. header_t first_atoms[256];
  34. code_t start_code;
  35. asize_t code_size;
  36.  
  37. static void init_atoms()
  38. {
  39.   int i;
  40.   for(i = 0; i < 256; i++) first_atoms[i] = Make_header(0, i, White);
  41. }
  42.  
  43. static unsigned long read_size(p)
  44.      unsigned char * p;
  45. {
  46.   return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16) +
  47.          ((unsigned long) p[2] << 8) + p[3];
  48. }
  49.  
  50. #define FILE_NOT_FOUND (-1)
  51. #define TRUNCATED_FILE (-2)
  52. #define BAD_MAGIC_NUM (-3)
  53.  
  54. static int read_trailer(fd, trail)
  55.      int fd;
  56.      struct exec_trailer * trail;
  57. {
  58.   char buffer[TRAILER_SIZE];
  59.  
  60.   lseek(fd, (long) -TRAILER_SIZE, 2);
  61.   if (read(fd, buffer, TRAILER_SIZE) < TRAILER_SIZE) return TRUNCATED_FILE;
  62.   trail->code_size = read_size(buffer);
  63.   trail->data_size = read_size(buffer+4);
  64.   trail->symbol_size = read_size(buffer+8);
  65.   trail->debug_size = read_size(buffer+12);
  66.   trail->magic = read_size(buffer+16);
  67.   if (trail->magic == EXEC_MAGIC) return 0; else return BAD_MAGIC_NUM;
  68. }
  69.  
  70. extern char * searchpath();
  71.  
  72. int attempt_open(name, trail, do_open_script)
  73.      char ** name;
  74.      struct exec_trailer * trail;
  75.      int do_open_script;
  76. {
  77.   char * truename;
  78.   int fd;
  79.   int err;
  80.   char buf [2];
  81.  
  82.   truename = searchpath(*name);
  83.   if (truename == 0) truename = *name; else *name = truename;
  84.   fd = open(truename, O_RDONLY | O_BINARY);
  85.   if (fd == -1) return FILE_NOT_FOUND;
  86.   if (!do_open_script){
  87.     err = read (fd, buf, 2);
  88.     if (err < 2) return TRUNCATED_FILE;
  89.     if (buf [0] == '#' && buf [1] == '!') return BAD_MAGIC_NUM;
  90.   }
  91.   err = read_trailer(fd, trail);
  92.   if (err != 0) { close(fd); return err; }
  93.   return fd;
  94. }
  95.  
  96. /* Invocation of camlrun: 4 cases.
  97.  
  98.    1.  runtime + bytecode
  99.        user types:  camlrun [options] bytecode args...
  100.        arguments:  camlrun [options] bytecode args...
  101.  
  102.    2.  bytecode script
  103.        user types:  bytecode args...
  104.    2a  (kernel 1) arguments:  camlrun ./bytecode args...
  105.    2b  (kernel 2) arguments:  bytecode bytecode args...
  106.  
  107.    3.  concatenated runtime and bytecode
  108.        user types:  composite args...
  109.        arguments:  composite args...
  110.  
  111. Algorithm:
  112.   1-  If argument 0 is a valid byte-code file that does not start with #!,
  113.       then we are in case 3 and we pass the same command line to the
  114.       Caml Light program.
  115.   2-  In all other cases, we parse the command line as:
  116.         (whatever) [options] bytecode args...
  117.       and we strip "(whatever) [options]" from the command line.
  118.  
  119. */
  120.  
  121. #ifdef HAS_UI
  122. int caml_main(argc, argv)
  123. #else
  124. int main(argc, argv)
  125. #endif
  126.      int argc;
  127.      char * argv[];
  128. {
  129.   int fd;
  130.   struct exec_trailer trail;
  131.   int i;
  132.   struct longjmp_buffer raise_buf;
  133.   struct channel * chan;
  134.   int verbose_init = 0, percent_free_init = Percent_free_def;
  135.   long minor_heap_init = Minor_heap_def, heap_chunk_init = Heap_chunk_def;
  136.   char * debugger_address = NULL;
  137. #ifdef MSDOS
  138.   extern char ** check_args();
  139.   argv = check_args(argv);
  140. #endif
  141.  
  142. #ifdef DEBUG
  143.   verbose_init = 1;
  144. #endif
  145.  
  146.   i = 0;
  147.   fd = attempt_open(&argv[0], &trail, 0);
  148.  
  149.   if (fd < 0) {
  150.  
  151.     for(i = 1; i < argc && argv[i][0] == '-'; i++) {
  152.       switch(argv[i][1]) {
  153. #ifdef DEBUG
  154.       case 't': {
  155.         extern int trace_flag;
  156.         trace_flag = 1;
  157.         break;
  158.       }
  159. #endif
  160.       case 'v':
  161.         verbose_init = 1;
  162.         break;
  163.       case 'V':
  164.         fprintf(stderr, "The Caml Light runtime system, version %s\n",
  165.                 VERSION);
  166.         exit(0);
  167.       default:
  168.         fatal_error_arg("Unknown option %s.\n", argv[i]);
  169.       }
  170.     }
  171.  
  172.     if (argv[i] == 0)
  173.       fatal_error("No bytecode file specified.\n");
  174.  
  175.     fd = attempt_open(&argv[i], &trail, 1);
  176.  
  177.     switch(fd) {
  178.     case FILE_NOT_FOUND:
  179.       fatal_error_arg("Fatal error: cannot find file %s\n", argv[i]);
  180.       break;
  181.     case TRUNCATED_FILE:
  182.     case BAD_MAGIC_NUM:
  183.       fatal_error_arg(
  184.         "Fatal error: the file %s is not a bytecode executable file\n",
  185.         argv[i]);
  186.       break;
  187.     }
  188.   }
  189.  
  190.   /* Runtime options.  The option letter is the first letter of the
  191.      last word of the ML name of the option (see [lib/gc.mli]). */
  192.  
  193.   { char *opt = getenv ("CAMLRUNPARAM");
  194.     if (opt != NULL){
  195.       while (*opt != '\0'){
  196.     switch (*opt++){
  197.     case 's': sscanf (opt, "=%ld", &minor_heap_init); break;
  198.     case 'i': sscanf (opt, "=%ld", &heap_chunk_init); break;
  199.     case 'o': sscanf (opt, "=%d", &percent_free_init); break;
  200.     case 'v': sscanf (opt, "=%d", &verbose_init); break;
  201.     }
  202.       }
  203.     }
  204.   }
  205.  
  206. #ifdef HAS_SOCKETS
  207.   if (debugger_address == NULL)
  208.     debugger_address = getenv("CAML_DEBUG_SOCKET");
  209. #endif
  210.  
  211.   if (setjmp(raise_buf.buf) == 0) {
  212.  
  213.     external_raise = &raise_buf;
  214.  
  215.     init_gc (minor_heap_init, heap_chunk_init, percent_free_init,
  216.          verbose_init);
  217.     init_stack();
  218.     init_atoms();
  219.  
  220.     lseek(fd, - (long) (TRAILER_SIZE + trail.code_size + trail.data_size
  221.                         + trail.symbol_size + trail.debug_size), 2);
  222.  
  223.     code_size = trail.code_size;
  224.     start_code = (code_t) stat_alloc(code_size);
  225.     if (read(fd, (char *) start_code, code_size) != code_size)
  226.       fatal_error("Fatal error: truncated bytecode file.\n");
  227.  
  228. #if defined(MOSML_BIG_ENDIAN) && !defined(ALIGNMENT)
  229.     fixup_endianness(start_code, code_size);
  230. #endif
  231.  
  232.     chan = open_descr(fd);
  233.     global_data = intern_val(chan);
  234.     modify(&Field(global_data, GLOBAL_DATA), global_data);
  235.     close_in(chan);
  236.  
  237.     sys_init(argv + i);
  238.     interprete(start_code);
  239.     sys_exit(Val_int(0));
  240.  
  241.   } else {
  242.  
  243.     if (exn_bucket == Atom(OUT_OF_MEMORY_EXN))
  244.       fatal_error ("Fatal error: out of memory.\n");
  245.     else
  246.       fatal_error ("Fatal error: uncaught exception.\n");
  247.   }
  248. }
  249.  
  250.